<?php

use LucaDegasperi\OAuth2Server\Authorizer;
use Rootant\Api\Exception\ValidationException;
use League\OAuth2\Server\Exception\InvalidCredentialsException;

class UserPasswordController extends CommonController
{
    public function __construct(Authorizer $authorizer)
    {
        parent::__construct($authorizer);
        $this->beforeFilter('oauth', ['except' => ['sendEmail', 'reset']]);
        $this->beforeFilter('validation');
        $this->afterFilter('disconnect:major', ['only' => ['modify', 'sendEmail', 'reset']]);
    }

    private static $_validate = [
        'modify' => [
            'old_password' => 'required',
            'new_password' => 'required|min:6|confirmed',
        ],
        'sendEmail' => [
            'email' => 'required|email|exists:user',
        ],
        'reset' => [
            'password' => 'required|min:6|confirmed',
        ],
    ];

    public function modify()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $oldPassword = Input::get('old_password');
        $newPassword = Input::get('new_password');

        $user = DB::table('user');

        $email = $user->find($uid)->email;
        // 校验用户的当前密码
        $this->validateCurrentPassword($email, $oldPassword);

        $item = $user->update(['password' => md5($newPassword)]);

        if ($item === 1) {
            // 如果是第三方用户的话，修改第三方用户的登录密码
            $this->updateThirdPartyUserPassword($email, $newPassword);
        }

        return (array) $user->find($uid);
    }

    /**
     * 模拟登录
     * 校验用户的当前密码
     *
     * @param  string $username 登录名
     * @param  string $password 密码
     * @return void
     *
     * @throws League\OAuth2\Server\Exception\InvalidCredentialsException
     */
    protected function validateCurrentPassword($username, $password)
    {
        $credentials = array(
                'email'    => $username,
                'password' => $password,
            );

        if (!Auth::once($credentials)) {
            throw new InvalidCredentialsException;
        }
    }

    /**
     * 如果是第三方用户修改密码的话
     *
     * @param  string $username    登录名
     * @param  string $newPassword 新密码
     * @return void
     */
    protected function updateThirdPartyUserPassword($username, $newPassword)
    {
        $updateData = array(
                'password'   => $newPassword,
                'updated_at' => date('Y-m-d H:i:s'),
            );
        $this->dbRepository('major', 'third_party_user_token')
            ->where('username', $username)
            ->update($updateData);
    }

    public function sendEmail()
    {
        MultiplexController::verifyCaptcha();

        $email = Input::get('email');

        $user = DB::table('user')
            ->select('id', 'name')
            ->where('email', $email)
            ->first();

        $checkStr   = MultiplexController::uuid();
        $insertData = array(
                'user_id'    => $user->id,
                'check_code' => $checkStr,
                'created_at' => date('Y-m-d H:i:s'),
                'expired_at' => date('Y-m-d H:i:s', time() + 12*60*60),
                'updated_at' => date('Y-m-d H:i:s'),
            );
        $this->dbRepository('major', 'password_email')
            ->insert($insertData);
        // 传递到邮件内容模板的视图变量
        $data = array('display_name' => $user->name, 'confirmed' => $checkStr);
        Mail::send('emails.view', $data, function($message) use ($email)
        {
            $message->to($email)->subject('重设密码');
        });
    }

    public function reset()
    {
        if (!Input::has('confirmation')) {
            throw new ApiException('参数丢失');
        }
        // 移除过期失效的数据
        $this->removeExpiredData();

        $this->confirmation = Input::get('confirmation');

        $passwordEmail = $this->dbRepository('major', 'password_email')
            ->where('check_code', $this->confirmation)
            ->first();

        if ($passwordEmail === null) {
            throw new ValidationException('链接或已失效，请重新找回密码！');
        }

        // 判断链接是否失效
        if (time() > strtotime($passwordEmail->expired_at)) {
            throw new ValidationException('重置密码链接已失效，请重新找回密码！');
        }

        $this->uid = $passwordEmail->user_id;

        $this->resetProcess();
    }

    /**
     * 移除过期失效的数据
     *
     * @return void
     */
    protected function removeExpiredData()
    {
        $this->dbRepository('major', 'password_email')
            ->where('expired_at', '<', date('Y-m-d H:i:s'))
            ->delete();
    }

    protected function resetProcess()
    {
        $this->password = Input::get('password');
        // 检查密码是否为上次密码
        $this->checkIsOriginPassword();
        // 重置密码
        $this->resetPassword();
        // 重置密码成功，移除密码重置链接对应数据
        $this->removeData();
    }

    protected function checkIsOriginPassword()
    {
        $email = DB::table('user')->where('id', $this->uid)->pluck('email');

        if (!$email) {
            return;
        }

        $credentials = array(
                'email'    => $email,
                'password' => $this->password,
            );
        if (Auth::once($credentials)) {
            throw new ValidationException('不能和上次密码一样:)');
        }
    }

    /**
     * [resetPassword description]
     * @return void
     */
    protected function resetPassword()
    {
        DB::table('user')->where('id', $this->uid)
            ->update(['password' => md5($this->password)]);
    }

    /**
     * [removeData description]
     * @return void
     */
    protected function removeData()
    {
        $this->dbRepository('major', 'password_email')
            ->where('check_code', $this->confirmation)
            ->delete();
    }

}